###   导入包   ###
import ply.lex as lex

###   是否打印详细信息   ###
LexerDebug = False


###   定义词法解析类   ###
class Lexer(object):
    def __init__(self):
        self.lexer = lex.lex(object=self)

    def input(self, text):
        self.lexer.input(text)

    def token(self):
        return self.lexer.token()

    ###   定义保留字，字典，静态变量   ###
    reserved = {
        'print': 'PRINT',

        'if': 'IF',
        'else': 'ELSE',
        'for': 'FOR',
        'while': 'WHILE',

        'break': 'BREAK',
        'continue': 'CONTINUE',

        'and': 'AND',
        'or': 'OR',

        'return': 'RETURN',

        'function': 'FUNCTION'
    }

    ###   定义token，静态变量   ###
    tokens = [
        # 变量名
        'NAME',
        # 整数，浮点数，字符串
        'INT', 'FLOAT', 'STRING',
        # 加，减，乘，除，模，赋值
        'PLUS', 'MINUS', 'TIMES', 'DIVIDE', 'MOD', 'ASSIGN',
        # (，)，[，]，{，}
        'LPAREN', 'RPAREN', 'LSQBRACK', 'RSQBRACK', 'LBRACK', 'RBRACK',
        # 大于，大于等于，小于，小于等于，等于，不等于，真，假，空
        'GT', 'GTE', 'LT', 'LTE', 'EQ', 'NEQ', 'TRUE', 'FALSE', 'NONE',
        # 冒号，分号，逗号，注释
        'COLON', 'SEMICOLON', 'COMMA', 'COMMENT',
    ]
    ###   将保留字和token合并到一块查询，静态变量   ###
    tokens = tokens + list(reserved.values())

    ###   声明正则表达式，顺序代表了优先级，静态变量   ###
    # 省略空格
    t_ignore = ' \t'

    # 特殊符号，需要转义
    # t_PLUS = '\+'
    def t_PLUS(self, t):
        '\+'
        if LexerDebug == True: print('t_PLUS')
        return t

    # t_MINUS = '-'
    def t_MINUS(self, t):
        '-'
        if LexerDebug == True: print('t_MINUS')
        return t

    # 特殊符号，需要转义
    # t_TIMES = '\*'
    def t_TIMES(self, t):
        '\*'
        if LexerDebug == True: print('t_TIMES')
        return t

    # t_DIVIDE = '/'
    def t_DIVIDE(self, t):
        '/'
        if LexerDebug == True: print('t_DIVIDE')
        return t

    # t_MOD = '%'
    def t_MOD(self, t):
        '%'
        if LexerDebug == True: print('t_DIVIDE')
        return t

    # 特殊符号，需要转义
    # t_LPAREN = '\('
    def t_LPAREN(self, t):
        '\('
        if LexerDebug == True: print('t_LPAREN')
        return t

    # 特殊符号，需要转义
    # t_RPAREN = '\)'
    def t_RPAREN(self, t):
        '\)'
        if LexerDebug == True: print('t_RPAREN')
        return t

    # 特殊符号，需要转义
    # t_LSQBRACK = '\['
    def t_LSQBRACK(self, t):
        '\['
        if LexerDebug == True: print('t_LSQBRACK')
        return t

    # 特殊符号，需要转义
    # t_RSQBRACK = '\]'
    def t_RSQBRACK(self, t):
        '\]'
        if LexerDebug == True: print('t_RSQBRACK')
        return t

    # 特殊符号，需要转义
    # t_LBRACK = '\{'
    def t_LBRACK(self, t):
        '\{'
        if LexerDebug == True: print('t_LBRACK')
        return t

    # 特殊符号，需要转义
    # t_RBRACK = '\}'
    def t_RBRACK(self, t):
        '\}'
        if LexerDebug == True: print('t_RBRACK')
        return t

    # t_EQ = '=='
    def t_EQ(self, t):
        '=='
        if LexerDebug == True: print('t_EQ')
        return t

    # t_ASSIGN = '='
    def t_ASSIGN(self, t):
        '='
        if LexerDebug == True: print('t_ASSIGN')
        return t

    # t_GTE = '>='
    def t_GTE(self, t):
        '>='
        if LexerDebug == True: print('t_GTE')
        return t

    # t_GT = '>'
    def t_GT(self, t):
        '>'
        if LexerDebug == True: print('t_GT')
        return t

    # t_LTE = '<='
    def t_LTE(self, t):
        '<='
        if LexerDebug == True: print('t_LTE')
        return t

    # t_LT = '<'
    def t_LT(self, t):
        '<'
        if LexerDebug == True: print('t_LT')
        return t

    # t_NEQ = '!='
    def t_NEQ(self, t):
        '!='
        if LexerDebug == True: print('t_NEQ')
        return t

    # t_COLON = ':'
    def t_COLON(self, t):
        ':'
        if LexerDebug == True: print('t_COLON')
        return t

    # t_SEMICOLON = ';'
    def t_SEMICOLON(self, t):
        ';'
        if LexerDebug == True: print('t_SEMICOLON')
        return t

    # t_COMMA = ','
    def t_COMMA(self, t):
        ','
        if LexerDebug == True: print('t_COMMA')
        return t

    # COMMENT = '\#.*'
    def t_COMMENT(self, t):
        '\#.*'
        # 省略
        pass

    def t_newline(self, t):
        r'\n+'
        if LexerDebug == True: print('t_newline')
        t.lexer.lineno += len(t.value)

    def t_TRUE(self, t):
        'True'
        if LexerDebug == True: print('t_TRUE')
        t.value = True
        return t

    def t_FALSE(self, t):
        'False'
        if LexerDebug == True: print('t_FALSE')
        t.value = False
        return t

    def t_NONE(self, t):
        'None'
        if LexerDebug == True: print('t_NONE')
        t.value = None
        return t

    def t_NAME(self, t):
        r'[a-zA-Z_][a-zA-Z_0-9]*'
        # 检查是不是关键词，如果不是，那么默认返回，NAME，
        t.type = Lexer.reserved.get(t.value, 'NAME')
        if LexerDebug == True: print('t_', t.type, ', value = ', t.value)
        return t

    def t_FLOAT(self, t):
        r'\d*\.\d+'
        t.value = float(t.value)
        if LexerDebug == True: print('t_FLOAT, value = ', t.value)
        return t

    def t_INT(self, t):
        r'\d+'
        t.value = int(t.value)
        if LexerDebug == True: print('t_INT, value = ', t.value)
        return t

    def t_STRING(self, t):
        r'\'(?:\\"|.)*?\''
        t.value = bytes(t.value.lstrip("'").rstrip("'"), "utf-8").decode("unicode_escape")
        if LexerDebug == True: print('t_STRING, value = ', t.value)
        return t

    def t_error(self, t):
        print("Lexer error = Illegal character '%s' at line '%d'" % (t.value[0], t.lexer.lineno))
        t.lexer.skip(1)

    def test(self, text):
        # Give the lexer some input
        self.lexer.input(text)
        for tok in self.lexer:
            print(tok)
